/*
 * MIT License
 *
 * Copyright (c) 2023 北京凯特伟业科技有限公司
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package com.je.meta.service.mybatis;

import com.je.common.base.DynaBean;
import com.je.common.base.service.rpc.FunctionService;
import com.je.ibatis.extension.metadata.IdType;
import com.je.ibatis.extension.metadata.model.Column;
import com.je.ibatis.extension.metadata.model.Function;
import com.je.ibatis.extension.metadata.model.Id;
import com.je.ibatis.extension.metadata.model.Table;
import com.je.ibatis.extension.parse.MetaDataParse;
import com.je.meta.rpc.table.ResourceTableService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import javax.sql.DataSource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;

public class ResourceCacheMetaDataParse implements MetaDataParse {

    @Autowired
    private ResourceTableService resourceTableService;

    @Autowired
    private FunctionService functionService;

    private DataSource dataSource;

    @Override
    public List<Table> tables() {
        List<DynaBean> list = resourceTableService.findAllTables();
        ArrayList<Table> tables = new ArrayList();
        list.forEach((p) -> {
            tables.add(this.parseTable(p));
        });
        return tables;
    }

    @Override
    public List<Table> tables(List<String> list) {
        List<DynaBean> tableList = resourceTableService.findTables(list);
        ArrayList<Table> tables = new ArrayList();
        tableList.forEach((p) -> {
            tables.add(this.parseTable(p));
        });
        return tables;
    }

    @Override
    public List<Function> functions() {
        List<DynaBean> list = functionService.findAllFunctions();
        ArrayList<Function> functions = new ArrayList();
        list.forEach((p) -> {
            functions.add(this.parseFunction(p));
        });
        return functions;
    }

    @Override
    public Table table(String s) {
        DynaBean tableBean = resourceTableService.findTable(s);
        return parseTable(tableBean);
    }

    @Override
    public Function function(String s) {
        DynaBean funcBean = functionService.findFunction(s);
        return funcBean == null ? null : this.parseFunction(funcBean);
    }

    @Override
    public void setDataSource(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    @Override
    public boolean formData(Table table, Map<String, Object> map) {
        return false;
    }

    protected Function parseFunction(DynaBean funcBean) {
        String id = funcBean.getStr("JE_CORE_FUNCINFO_ID");
        String code = funcBean.getStr("FUNCINFO_FUNCCODE");
        String name = funcBean.getStr("FUNCINFO_FUNCNAME");
        String tableCode = funcBean.getStr("FUNCINFO_TABLENAME");
        String lazy = funcBean.getStr("FUNCINFO_COLUMNLAZY");
        Assert.notNull(code, "field[JE_CORE_FUNCINFO_ID] is null!");
        List<String> loadColumnNames = new ArrayList();
        List<DynaBean> columnList = functionService.findResourceColumnByFunctionId(id);
        if ("1".equalsIgnoreCase(lazy.toString())) {
            columnList.forEach((c) -> {
                loadColumnNames.add(c.getStr("RESOURCECOLUMN_CODE"));
            });
        }
        return tableCode == null ? new Function(code.toString(), (String) null, loadColumnNames) : new Function(code.toString(), tableCode.toString(), loadColumnNames);
    }

    protected Table parseTable(DynaBean tableBean) {
        String tableId = tableBean.getStr("JE_CORE_RESOURCETABLE_ID");
        String tableName = tableBean.getStr("RESOURCETABLE_TABLENAME");
        String tableCode = tableBean.getStr("RESOURCETABLE_TABLECODE");
        Object keyIgnoreCase = tableBean.get("RESOURCETABLE_KEY_GENERATOR_TYPE");
        Object incrementerName = tableBean.get("RESOURCETABLE_INCREMENTER_NAME");
        Object generatorSql = tableBean.get("RESOURCETABLE_KEY_GENERATOR_SQL");
        Assert.notNull(tableId, "field[JE_CORE_RESOURCETABLE_ID] is null!");
        Assert.notNull(tableCode, String.format("id[%s] field[RESOURCETABLE_TABLECODE] is null!", tableId));

        Table table = new Table();
        table.setCode(tableCode.toString());
        table.setName(tableName == null ? null : tableName.toString());
        List<DynaBean> columnList = resourceTableService.findTableColumns(tableId);
        columnList.forEach((c) -> {
            Column column = this.parseColumn(c);
            if ("ID".equalsIgnoreCase(column.getType())) {
                table.setId(new Id(column.getCode(), IdType.getIdType(keyIgnoreCase), Objects.toString(incrementerName), Objects.toString(generatorSql)));
            }

            table.addColumn(column);
        });
        if (table.getId() == null) {
            List<DynaBean> keys = resourceTableService.findTableColumns(tableId);
            if (keys != null && !keys.isEmpty()) {
                if (keys.size() > 1) {
                }
                Object pkCode = ((Map) keys.get(0)).get("TABLEKEY_COLUMNCODE");
                table.setId(new Id(pkCode.toString(), IdType.getIdType(keyIgnoreCase), Objects.toString(incrementerName), Objects.toString(generatorSql)));
            }
        }

        return table;
    }

    protected Column parseColumn(DynaBean columnBean) {
        String columnCode = columnBean.getStr("TABLECOLUMN_CODE");
        String columnName = columnBean.getStr("TABLECOLUMN_NAME");
        String columnType = columnBean.getStr("TABLECOLUMN_TYPE");
        String columnLength = columnBean.getStr("TABLECOLUMN_LENGTH");
        Object isNull = columnBean.get("TABLECOLUMN_ISNULL");

        if ("DATETIME".equalsIgnoreCase(String.valueOf(columnType)) || "DATE".equalsIgnoreCase(String.valueOf(columnType))) {
            columnType = "VARCHAR";
        }

        if ("CUSTOM".equalsIgnoreCase(String.valueOf(columnType)) && !StringUtils.isEmpty(columnLength)) {
            columnType = columnLength;
        }

        Boolean isNullBoolean = false;
        if (String.valueOf(isNull) != null && String.valueOf(isNull).equals("1")) {
            isNullBoolean = true;
        }
        Assert.notNull(columnCode, "field[TABLECOLUMN_CODE] is null!");
        return new Column(String.valueOf(columnCode), String.valueOf(columnName), String.valueOf(columnType), isNullBoolean);
    }

}
